#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/pagemap.h>
#include "myfs.h"
// 定义目录操作
const struct file_operations myfs_dir_ops = {
    .open		= dcache_dir_open,
	.release	= dcache_dir_close,
	.llseek		= dcache_dir_lseek,
	.read		= generic_read_dir,
	.iterate_shared	= dcache_readdir,
	.fsync		= noop_fsync,
};
static struct myfs_inode *get_myfs(struct file *file)
{
    if (!file || !file->f_inode) {
        return NULL;  // 检查输入的有效性
    }

    // 获取关联的 inode 的 i_private
    return (struct myfs_inode*)file->f_inode->i_private;
}

// 打开文件时的操作
int myfs_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "myfs: opening file\n");

    // 追加写入操作, 移动文件指针到文件末尾
    if (file->f_flags & O_APPEND){
        generic_file_llseek(file, 0, SEEK_END);
    }
    
    return 0;
}

// 读取文件内容
ssize_t myfs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 
{
    struct myfs_inode *my_inode = get_myfs(file);

    // 如果文件偏移量大于文件内容，返回0表示文件结束
    if (*ppos >= my_inode->len) 
        return 0;

    // 调整读取的字节数，避免越界
    if (*ppos + count > my_inode->len)
        count = my_inode->len - *ppos;

    // 将文件内容复制到用户空间
    if (copy_to_user(buf, my_inode->data + *ppos, count))
        return -EFAULT;

    *ppos += count;  // 更新文件偏移量
    return count;
}

// 写入数据到文件
ssize_t myfs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
    struct inode *inode = file->f_inode;
    struct myfs_inode *my_inode = get_myfs(file);
    char *new_data;
    size_t new_len = *ppos + count;


    // 重新分配内存
    new_data = krealloc(my_inode->data, new_len + 1, GFP_KERNEL);
    if (!new_data)
        return -ENOMEM;

    my_inode->data = new_data;
    my_inode->len = new_len;

    // 将用户空间的数据拷贝到内存
    if (copy_from_user(my_inode->data + *ppos, buf, count))
        return -EFAULT;

    my_inode->data[new_len] = '\0';  // 确保字符串结尾

    *ppos += count;  // 更新文件偏移量
    // 更新文件大小
    inode->i_size = max(inode->i_size, my_inode->len); 
    mark_inode_dirty(inode);

    return count;
}

// 释放文件时的操作
int myfs_release(struct inode *inode, struct file *file) {
    printk(KERN_INFO "myfs: closing file\n");
    return 0;
}

/**
 * myfs_mmu_get_unmapped_area - get an address range for mapping a file.
 * @file: the struct file to map
 * @addr: the starting address to map.  If this is 0, the kernel will pick one.
 * @len: the length of the mapping
 * @pgoff: the offset of the mapping in the file
 * @flags: the mapping flags.  See mmap(2) for a list of valid flags.
 *
 * This function should return an address range that the kernel can use to
 * map the file.  If the function returns 0, the kernel will pick an address.
 */
static unsigned long myfs_mmu_get_unmapped_area(struct file *file,
		unsigned long addr, unsigned long len, unsigned long pgoff,
		unsigned long flags)
{
	return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
}

// 定义文件操作
const struct file_operations myfs_file_ops = {
    .open = myfs_open,
    // 老版本的read, 更直观, 容易理解, 但是用这个实现的文件系统无法执行ELF文件, 
    // 因为内核使用kernel_read读取ELF文件, 而kernel_read依赖read_iter
    //.read = myfs_read,
    //.write = myfs_write,
    .release = myfs_release,
	.llseek		= generic_file_llseek,
    // 新版本的read, 更高效
    .read_iter	= generic_file_read_iter,
	.write_iter	= generic_file_write_iter,
    // mmap 操作
	.mmap		= generic_file_mmap,
	.get_unmapped_area	= myfs_mmu_get_unmapped_area,
    // splice 操作zero copy
	.splice_read	= filemap_splice_read,
	.splice_write	= iter_file_splice_write,
    .fsync		= noop_fsync,
};
// 生成inode
struct inode *myfs_get_inode(struct super_block *sb, const struct inode *dir, int mode, dev_t dev) 
{
    struct inode *inode = new_inode(sb);  // 创建新的inode
    struct myfs_inode *my_inode;

    if (!inode)
        return NULL;

    // 为inode分配内存
    my_inode = kmalloc(sizeof(*my_inode), GFP_KERNEL);
    if (!my_inode) {
        iput(inode);  // 如果分配失败，释放inode
        return NULL;
    }

    inode->i_ino = get_next_ino();  // 获取唯一的inode编号
	inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
	// 地址空间操作, 支持内存映射
    inode->i_mapping->a_ops = &ram_aops;  // 地址空间操作
	mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
	mapping_set_unevictable(inode->i_mapping);

	// 设置新创建的inode的时间戳
	simple_inode_init_ts(inode);

	switch (mode & S_IFMT) {
	default:
		init_special_inode(inode, mode, dev);
		break;
    case S_IFDIR:
        inode->i_op = &myfs_dir_inode_ops;  // 设置inode操作
        inode->i_fop = &myfs_dir_ops;  // 设置目录操作
		break;
	case S_IFREG:
        inode->i_op = &myfs_file_inode_ops;  // 设置inode操作
        inode->i_fop = &myfs_file_ops;  // 设置文件系统操作
		break;
	case S_IFLNK:
		inode->i_op = &page_symlink_inode_operations;
		inode_nohighmem(inode);
		break;
    }

	// 自定义数据初始化
    my_inode->data = NULL;
	my_inode->len = 0;  
    inode->i_private = my_inode;  // 将自定义的myfs_inode关联到vfs_inode

    return inode;
}

/*
 * File creation. Allocate an inode, and we're done..
 */
/* SMP-safe */
static int
myfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
	    struct dentry *dentry, umode_t mode, dev_t dev)
{
	struct inode * inode = myfs_get_inode(dir->i_sb, dir, mode, dev);
	int error = -ENOSPC;

	if (inode) {
		d_instantiate(dentry, inode);
		dget(dentry);	/* Extra count - pin the dentry in core */
		error = 0;
		inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
	}
	return error;
}

static int myfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
		       struct dentry *dentry, umode_t mode)
{
	int retval = myfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0);
	if (!retval)
		inc_nlink(dir);
	return retval;
}

static int myfs_create(struct mnt_idmap *idmap, struct inode *dir,
			struct dentry *dentry, umode_t mode, bool excl)
{
	return myfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFREG, 0);
}

static int myfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
			 struct dentry *dentry, const char *symname)
{
	struct inode *inode;
	int error = -ENOSPC;

	inode = myfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0);
	if (inode) {
		int l = strlen(symname)+1;
		error = page_symlink(inode, symname, l);
		if (!error) {
			d_instantiate(dentry, inode);
			dget(dentry);
			inode_set_mtime_to_ts(dir,
					      inode_set_ctime_current(dir));
		} else
			iput(inode);
	}
	return error;
}

static int myfs_tmpfile(struct mnt_idmap *idmap,
			 struct inode *dir, struct file *file, umode_t mode)
{
	struct inode *inode;

	inode = myfs_get_inode(dir->i_sb, dir, mode, 0);
	if (!inode)
		return -ENOSPC;
	d_tmpfile(file, inode);
	return finish_open_simple(file, 0);
}

// 文件的 inode 操作
struct inode_operations myfs_file_inode_ops = {
    .setattr = simple_setattr,
    .getattr = simple_getattr,
};

// 目录的inode操作
struct inode_operations myfs_dir_inode_ops = {
	.create		= myfs_create,
	.lookup		= simple_lookup,
	.link		= simple_link,
	.unlink		= simple_unlink,
	.symlink	= myfs_symlink,
	.mkdir		= myfs_mkdir,
	.rmdir		= simple_rmdir,
	.mknod		= myfs_mknod,
	.rename		= simple_rename,
	.tmpfile	= myfs_tmpfile,
};
// 超级块操作定义
struct super_operations myfs_super_ops = {
    .statfs = simple_statfs,  // 获取文件系统的状态
    .drop_inode = generic_delete_inode,  // 使用默认的drop_inode实现
};

// 填充超级块信息
static int myfs_fill_super(struct super_block *sb, void *data, int silent) {
    sb->s_magic = MYFS_MAGIC;  // 设置文件系统的魔数
    sb->s_op = &myfs_super_ops;  // 设置超级块操作
    sb->s_fs_info = NULL;  // 没有额外的文件系统信息

    // 创建根目录inode，并将其设置为超级块的根目录
    struct inode *root_inode = myfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
    if (!root_inode)
        return -ENOMEM;  // 内存分配失败

    sb->s_root = d_make_root(root_inode);  // 创建根目录的dentry
    if (!sb->s_root) {
        iput(root_inode);  // 如果创建失败，释放root_inode
        return -ENOMEM;
    }

    return 0;
}

// 挂载文件系统
static struct dentry *myfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) {
    return mount_nodev(fs_type, flags, data, myfs_fill_super);  // 使用无设备挂载
}

// 卸载文件系统时的操作
static void myfs_kill_super(struct super_block *sb) {
    pr_info("myfs: superblock is being killed\n");
}

// 文件系统类型定义
static struct file_system_type myfs_type = {
    .name = "myfs",  // 文件系统名称
    .mount = myfs_mount,  // 挂载函数
    .kill_sb = myfs_kill_super,  // 卸载函数
    .owner = THIS_MODULE,  // 模块所有者
};

// 初始化文件系统模块
static int __init myfs_init(void) {
    printk(KERN_INFO "init start \n");
    int ret = register_filesystem(&myfs_type);  // 注册文件系统
    if (ret)
        printk(KERN_ERR "myfs: unable to register myfs %d\n",ret);
    else
        printk(KERN_INFO "myfs: myfs registered %d\n",ret);

    return ret;
}

// 清理文件系统模块
static void __exit myfs_exit(void) {
    unregister_filesystem(&myfs_type);  // 卸载文件系统
    printk(KERN_INFO "myfs: myfs unregistered\n");
}

// 模块入口和出口
module_init(myfs_init);
module_exit(myfs_exit);

// 模块信息
MODULE_LICENSE("GPL");
MODULE_AUTHOR("kevin");
MODULE_DESCRIPTION("A simple in-memory filesystem");
